'use strict';

/**
 * #################
 * 兼容处理: 
 * @default window.requestAnimationFrame
 * @default window.cancelAnimationFrame
 * 
 * @desc 用于定时循环操作, 按帧对网页进行重绘, 节省CPU、GPU和电力
 * @see https://javascript.ruanyifeng.com/htmlapi/requestanimationframe.html 
 */

import './performance-now';

~function (root) {
    var vendors = ['ms', 'moz', 'webkit', 'o'],
        suffix = 'AnimationFrame',
        raf = root['request' + suffix],
        caf = root['cancel' + suffix] || root['cancelRequest' + suffix],
        now = performance.now;

    for (var i = 0; !raf && i < vendors.length; i++) {
        raf = root[vendors[i] + 'Request' + suffix];
        caf = root[vendors[i] + 'Cancel' + suffix] || root[vendors[i] + 'CancelRequest' + suffix];
    }

    if (!raf || !caf) {
        var last = 0,
            id = 0,
            queue = [],
            frameDuration = 1000 / 60;

        raf = function (callback) {
            if (queue.length === 0) {
                var _now = now(), next = Math.max(0, frameDuration - (_now - last));

                last = next + _now;

                var timer = setTimeout(function () {
                    var cp = queue.slice(0);

                    queue.length = 0;

                    for (var i = 0; i < cp.length; i++) {
                        if (!cp[i].cancelled) {
                            try {
                                cp[i].callback(last);
                            } catch (e) {
                                setTimeout(function () { throw e }, 0);
                            }
                        }
                    }
                }, Math.round(next));
            }

            queue.push({
                handle: ++id,
                callback: callback,
                cancelled: false,
                timer: timer
            });

            return id;
        };

        caf = function (handle) {
            for (var i = 0; i < queue.length; i++) {
                if (queue[i].handle === handle) {
                    queue[i].cancelled = true;
                    clearTimeout(queue[i].timer);
                }
            }
        };
    }

    root.requestAnimationFrame = raf;
    root.cancelAnimationFrame = caf;
}(window);